package com.qianfeng.smartdevice.events.listeners;

import com.qianfeng.smartdevice.enums.LoginResutEnum;
import com.qianfeng.smartdevice.events.MyLoginEvent;
import com.qianfeng.smartdevice.mapper.SysLogininforMapper;
import com.qianfeng.smartdevice.mapper.SysUserOnlineMapper;
import com.qianfeng.smartdevice.pojo.SysLogininfor;
import com.qianfeng.smartdevice.pojo.SysUserOnline;
import com.qianfeng.smartdevice.utils.RequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @time: 2022-03-17 14:31
 */
@Component
//@EnableAsync//开启异步支持,  @Async才会有效,这个注解只需要写一次
public class LoginEventListener {

    private SysUserOnlineMapper sysUserOnlineMapper;
    private SysLogininforMapper sysLogininforMapper;

    @Autowired
    public void setSysUserOnlineMapper(SysUserOnlineMapper sysUserOnlineMapper) {
        this.sysUserOnlineMapper = sysUserOnlineMapper;
    }

    @Autowired
    public void setSysLogininforMapper(SysLogininforMapper sysLogininforMapper) {
        this.sysLogininforMapper = sysLogininforMapper;
    }

    Logger logger = LoggerFactory.getLogger(LoginEventListener.class);

    @EventListener
    // @Async//异步执行
    public void onEvent(MyLoginEvent event) {
        logger.error("收到登录操作的事件了");
        //我们现在只有登录的结果和用户名,还差和请求相关的所有的数据, ip 区域,操作系统等等
        //这些数据都可以从请求中获取
        //请求对象,我们发现我们少了一request对象

        //因为是通过threadlocal获取的数据,所以拿的时候不能放到子线程
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        CompletableFuture.runAsync(() -> {
                    HttpServletRequest request = requestAttributes.getRequest();
                    String sessionId = request.getSession().getId();//获取到sessionid
                    String ip = RequestUtil.getRemoteHost(request);//获取到ip
                    Map<String, String> osAndBrowserInfo = RequestUtil.getOsAndBrowserInfo(request);//获取操作系统和浏览器的信息
                    String locationByIp = RequestUtil.getLocationByIp(ip);//s取到ip对应的地区
                    //保存数据到对象中
                    SysLogininfor sysLogininfor = new SysLogininfor();
                    sysLogininfor.setIpaddr(ip);
                    sysLogininfor.setLoginLocation(locationByIp);
                    sysLogininfor.setLoginName(event.getUserName());
                    sysLogininfor.setLoginTime(new Date());
                    sysLogininfor.setBrowser(osAndBrowserInfo.get("browser"));
                    sysLogininfor.setOs(osAndBrowserInfo.get("os"));
                    switch (event.getLoginResutEnum()) {
                        case SUCCESS:
                            sysLogininfor.setMsg("登录成功");
                            sysLogininfor.setStatus("1");
                            break;
                        case FAIL:
                            sysLogininfor.setMsg("登录失败");
                            sysLogininfor.setStatus("0");
                            break;
                    }
                    System.err.println(sysLogininfor);
                    //保存到数据库
                    sysLogininforMapper.addLoginLog(sysLogininfor);
                    if (event.getLoginResutEnum() == LoginResutEnum.SUCCESS) {
                        //在登录成功之后还需要更新下在线用户
                        //在线用户的数据中我们只有一个数据不知道, sessionid,我们已经拿到request,只需要通过它拿到session id
                        SysUserOnline sysUserOnline = new SysUserOnline();
                        BeanUtils.copyProperties(sysLogininfor, sysUserOnline);
                        sysUserOnline.setSessionId(sessionId);
                        sysUserOnline.setExpireTime(30L);
                        sysUserOnline.setStartTimestamp(new Date());
                        logger.error("在线用户的数据对象" + sysUserOnline);
                        //保存到数据库
                        //经过测试我们发现下次登录的时候会报错,因为这个用户的数据已经存在了一条,其实只要更新即可
                        //更新sessionid和登录时间地点即可
                        int count = sysUserOnlineMapper.findByUserName(sysUserOnline.getLoginName());
                        if (count == 1) {
                            //更新数据
                            sysUserOnlineMapper.updateSysUserOnline(sysUserOnline);
                        } else {
                            //添加数据
                            sysUserOnlineMapper.addSysUserOnline(sysUserOnline);
                        }
                    }
                }
        );
    }
}
